PECompact
©1999-2002 by Collake Software
All Rights Reserved.
Email: support@collakesoftware.com
Homepage:
http://www.CollakeSoftware.com/
This software is provided as-is, without warranty of ANY KIND, either expressed or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose. The author shall NOT be held liable for ANY damage to you, your computer, or to anyone or anything else, that may result from its use, or misuse. Basically, you use it at YOUR OWN RISK. Registration is required to continue using this software after a 14-day evaluation period has expired. Please see the registration information at the end of this document.
I. Overview
PECompact is a utility that compresses Windows 9x/NT4/w2k
portable executables (EXE, DLL, SCR, OCX, etc..) significantly while leaving
them 100% functional. PECompact’d applications occupy less disk space,
cost less to distribute, are more fault tolerant, are loaded quicker across
networks, decrease network traffic, and are more difficult to reverse-engineer
and modify.
PECompact works by compressing the code, data, import directory,
selected resources, and other portions of Windows portable executables. At
runtime, the executable is rebuilt in memory with no noticeable delay; the
executable is at no time extracted to disk. In fact, compressed executables can
actually load quicker in some cases because there is less data to be retrieved
from the disk or network, which is usually the largest bottleneck. Both
compression algorithms used by PECompact feature an optimized, 32bit x86
assembly language decompressor for maximum data throughput.
This tool is highly configurable and gives the user a great
deal of power to select what and how things are compressed. PECompact also has
unique plug-in support to allow users to supply their own encryption/decryption
procedures or special functionality to compressed executables.
For users who prefer not to compress their executables for
whatever reason, PECompact also offers a “Trim Only” option that
optimizes the executable structure and decreases its size without applying any
compression at all! This function can optionally strip relocations from the
executable.
Features
II. Usage
PECompact
analyzes the target executable and auto-configures itself for those users who
prefer not to get involved with the intricate details of the compression. However,
to support more advanced users, PECompact is the most configurable executable
compressor on the market.
1. The Main Dialog
Function
Name
Description
Compress Normal Application |
Compress file as a normal EXE. |
Compress DLL/OCX |
Compress file as a Dynamic-Link
Library or OCX control. |
Trim Only |
Realign and optimize the
executable structure without applying any compression or installing any
symbiotic code. Relocations are stripped from EXEs, and left preserved in
DLLs. |
aPLib |
Utilize Joergen Ibsen’s
aPLib data compression library. This compression library is fast and tight,
especially for files smaller than 64k. This option can also be selected by using
the command line switch “/J”. |
JCALG1 |
Utilize Jeremy Collake’s
JCALG1 compression library. This compression library supports multiple
compress level settings and performs better than aPLib on larger files. This
option can also be selected by using the command line switch
“/J-“. |
Compression Level |
This trackbar allows the user to
select the compression level that JCALG1 will use. A higher level (farther to
the right) will use a larger window size, thereby increasing the compression
level but decreasing the compression speed. Note that higher compression
levels will require significantly more memory during compression.
Decompression speed and memory requirements are unaffected. |
Browse |
Browse for and select a file to
compress or trim. |
Compress/Trim |
Begin compression or trimming of
an executable. |
Test |
Test the compressed executable,
with an option to restore the backup. |
Erase .BAK |
Erase backup of compressed
executable. |
Exit |
Exit PECompact. |
Advanced Configuration |
Show the advanced configuration
dialog. See below for explanation of options there. |
2. Advanced Configuration
Create New Section |
Places the PECompact symbiotic
code into a new section of the executable rather than the default of appending
it to the last section. Checking this option may result in a slightly larger
compressed executable. |
Restructure Resources |
Restructure the resources in a
more compressible format. Turning this option off will hinder compression of
some resources in the executable. |
Merge Sections |
Merge congruent, compressible
sections into one section to reduce file alignment overhead. Turning this
option off will result in a larger compressed executable, but slightly faster
loading. |
Strip Relocations |
Strip the relocations (fixups)
from the executable. It is safe to strip the relocations from EXEs, but one
should NEVER strip the relocations from DLLs. |
Compress Export Table |
Compress the export table, if it
exists. This option is not recommended. |
Relocate Export Table |
The export table is moved to an
uncompressed area of the file so that the section originally containing the
export table may be compressed. This results in better compression. |
Use Windows DLL Loader |
Allow the windows loader to
process the import directory instead of the PECompact symbiotic code. |
Copy Overlay |
Some executables, such as setup
applications, have extra data appended to the end. Selecting this option will
cause any extra data to be copied to the end of the compressed executable. |
Skip Shared Sections |
Toggle on or off the skipping of compression of shared data sections. Shared data sections are often used by dynamic link libraries so that multiple instances of the module in different process spaces may share data. If this toggle is left OFF, the shared flag is removed from any shared sections and they are compressed as normal. Otherwise, the shared section is skipped and its data is available for sharing across processes. |
Backup File |
Create a backup of the file
before compression. The backup will be named the same as the original, except
it will have the “.bak” extension appended to it. |
Small/Fast Decompressor |
The small decompressor is
smaller, yet slower than the fast decompressor. The size difference is about
150 bytes, but the fast decompressor could cause an increase in executable
size by as much as 512 bytes. |
Skip Checksum |
Toggle checksum calculation by decompressor. By default, a checksum is calculated and compared for every decompressed block and once after code reconstruction. If any data corruption is found, a Message Box is displayed alerting the user. Turning checksumming off may decrease decompression and reconstruction time (execution latency) by ~30%. |
Plug-ins - Encrypt |
Select the encryption plug-in. |
Plug-ins – Pre-operative |
Select the pre-operative plug-in. This plug-in is described in the Plug-ins documentation. |
Plug-ins - Post-operative |
Select the post-operative
plug-in. |
Plug-ins – GPA |
Select the GetProcAddress hook
plug-in. |
Plug-ins - ExtraData |
Select the ExtraData plug-in. This plug-in is simply a file of text or binary type that contains data (such as a copyright message) that will be inserted by PECompact into the compressed executable’s slack header space (the header will be expanded if necessary). |
Finish Beep |
Emit beep when compression of a file
is complete. |
One Instance |
Only allow one instance of
PECompact to be active at a time. |
Lock Memory in RAM |
Lock allocated memory into RAM
if possible. |
Compressible Resources |
This list of resources allows
for selection of which resources should be compressed, and which should
remain uncompressed and preserved. |
Unknown Types (Resources) |
This toggle allows you to set
the compression of unknown resource types. ActiveX controls should turn this
toggle off. |
All Shell Icons |
Compress all shell icons,
leaving none available for display by explorer and other applications. |
# of Shell Icons |
The maximum number of icons to
leave uncompressed and available for display by explorer and other applications.
Decreasing this number will result in greater compression of most executables. |
3. Menu Options
Configuration / Save |
Save the current configuration to a file. |
Configuration
/ Save Configuration |
Save the current configuration to a file, and select a new filename. |
Configuration
/ Load Configuration |
Load a saved configuration. |
Configuration
/ Restore Defaults |
Restore
the default configuration. |
Help
/ About |
Display
the about box and registration status. |
Help
/ Check For Update |
Check
for an update on Collake Software’s website. |
B. Command Line Switches
PECompact can be run without any parameters,
however it also accepts the following command line syntax:
PECompact [filename] [switches]
/A |
Automatically
start compression or trimming without any user intervention. |
/X |
Automatically
exit after compression or trimming is complete. |
/T |
Toggle on/off trim only mode. |
/M[-] |
Toggle
on/off section merging. |
/C[-] |
Toggle
on/off resource restructuring. |
/L[-] |
Toggle
on/off usage of windows DLL loader. |
/E[-] |
Toggle
on/off compression of the export table. |
/K[-] |
Toggle
on/off relocation of the export table. |
/I[-] |
Toggle
on/off compression of all shell icons. |
/B[-] |
Toggle
on/off backup of file. |
/O[-] |
Toggle
on/off copying of overlay. |
/S[-] |
Toggle
on/off stripping of relocations. |
/R[-] |
Register
or unregister shell extension. |
/J[-] |
Toggle
usage of aPLib. |
/0-9 |
Specify
compression level for use by JCALG1. |
/F[-] |
Toggle
usage of fast decompression procedure. |
/P[-] |
Toggle
progress bar. |
/U[-] |
Toggle
compression of unknown resources. ActiveX controls should use /U-. |
/#[-] |
Toggle checksum calculation by decompressor. By default, a checksum is calculated and compared for every decompressed block and once after code reconstruction. If any data corruption is found, a Message Box is displayed alerting the user. Turning checksumming off may decrease decompression and reconstruction time (execution latency) by ~30%. |
/![-] |
Toggle on or off the skipping of compression of shared data sections. Shared data sections are often used by dynamic link libraries so that multiple instances of the module in different process spaces may share data. If this toggle is left OFF, the shared flag is removed from any shared sections and they are compressed as normal. Otherwise, the shared section is skipped and its data is available for sharing across processes. |
/$ConfigFile=FILE |
Specify the configuration file to use. |
/$StackReserve=00000000 |
Specify,
in hexidecimal, the stack reserve size to set in compressed executables. |
/$Encryption=FILE |
Specify the encryption plug-in file, given where ‘FILE’. |
/$Decryption=FILE |
Specify the decryption plug-in file, given where ‘FILE’. |
/$PreOperational=FILE |
Specify the pre-operational plug-in file, given where ‘FILE’. |
/$PostOperational=FILE |
Specify the post-operational plug-in file, given where ‘FILE’. |
/$GetProcAddressHook=FILE |
Specify the GetProcAddressHook plug-in file, given where ‘FILE’. |
/$ExtraData=FILE |
Specify the ExtraData plug-in file, given where ‘FILE’. |
|
Extra input data will be supplied to the Encryption plug-in, if one exist, upon initialization via InitEncryptionPlug-inV2. |
*Command line switches override a saved configuration.
C. Using with batch files in Windows95/98/Me
Windows 95/98/Me do not, by default, wait for termination of a GUI subsystem executable before continuing on with execution of the batch file from which the application was launched. To get around this issue, use the ‘Start’ utility with the command line parameter, ‘/WAIT’.
e.g.: Start /WAIT pecompact.exe
myfile.exe /A /X
Plug-ins allow for third party developers to embed code into compressed executables to be subsequently invoked at runtime by the PECompact loader. For programming convenience, they are implemented in DLLs with named exports. PECompact retrieves the address for the appropriately named export (each plug-in has a different export name) and then copies the procedure (up to MAX_SIZE) if it is a TRANSIENT plug-in (see plug-in type) to an arbitrary location for execution by the compressed executable at runtime, or merely invokes the plug-in function from the DLL if it is a STATIC plug-in.
Starting in PECompact v1.60, a new plug-in interface has been introduced. This interface is much improved over the last one and allows for potential development of PECompact plug-ins in high level languages. All plug-ins use the STDCALL calling convention (please remember ebx, esi, edi, ebp register preservation rules, they will be strictly enforced in later versions).
Very useful sample plug-ins written in MASM are located in the PLUG-INSV2.ZIP file of your PECompact installation folder.
This new interface is much more robust than the previous. Amongst many of its benefits, it offers a resident data storage in which the all plug-ins may store data and communicate with one another (this data remains intact for both TRANSIENT and STATIC type plug-ins, meaning that STATIC plug-ins may store data here that TRANSIENT plug-ins may subsequently access at runtime). This resident data area, and its size, is passed to each plug-in. Additionally, each plug-in is passed the addresses of LoadLibraryA and GetProcAddress.
The two
types of plug-ins:
STATIC
These plug-ins are executed directly in the DLL they reside in. They have no
maximum size and no other restrictions.
TRANSIENT
These
plug-ins will be copied from the DLL they reside in to the loader placed onto
compressed executables. They will be executed at runtime of the
compressed executable. Therefore, these plug-ins have certain restrictions:
1.) They must reside in a contiguous block (both data and code together)
starting at the address of their export procedure and must not exceed
maximum size specified.
2.) They must calculate and apply a delta offset to all static code and data references.
3.) Please see sample plug-ins for templates and examples.
Pre-Operative Plug-in
Brief: This plug-in is copied into the PECompact loader placed
into the host executable. It is invoked at runtime before any decompression or
reconstruction of the host executable occurs.
Export Name: PreOperativePluginV2
Maximum Size: 512 bytes
Plug-in Type: TRANSIENT
C Prototype:
DWORD PreOperativePluginV2(HMODULE pLoadLibrary,
LPVOID pGetProcAddress,
LPVOID pResidentData,
DWORD nResidentDataSize,
LPVOID pImageBase,
PPEC_DATA_BLOCK_INFO pDataBlockInfoArray);
ASM Prototype:
PreOperativePluginV2 PROTO stdcall pLoadLibrary:DWORD,\
pGetProcAddress:DWORD,\
pResidentData:DWORD,\
nResidentDataSize:DWORD,\
pImageBase:DWORD,\
pDataBlockInfoArray:DWORD
Return Value:
ERROR_SUCCESS (0) = success, continue decompression/reconstruction.
ERROR_FATAL (1) = error, this process should immediately exit.
Parameter Descriptions:
pLoadLibrary = pointer to LoadLibraryA.
pGetProcAddress = pointer to GetProcAddress.
pResidentData = pointer to the resident data storage area.
nResidentDataSize = size, in bytes, of the resident data.
pImageBase = pointer to the image base of the application.
pDataBlockInfoArray = pointer to an array PEC_DATA_BLOCK_INFO records.
typedef struct _PEC_DATA_BLOCK_INFO
{
PVOID pBlockRVA;
ULONG nCompressedSize;
} PEC_DATA_BLOCK_INFO, *PPEC_DATA_BLOCK_INFO;
Notes:
None.
Post-Operative Plug-in
Brief: This plug-in is copied into the PECompact loader placed into the host executable. It is invoked at runtime after all decompression and reconstruction of the host executable is complete and control is about to be passed back to the original entry point.
Export Name: PostOperativePluginV2
Maximum Size: 512 bytes
Plug-in Type: TRANSIENT
C Prototype:
DWORD PostOperativePluginV2(HMODULE pLoadLibrary,
LPVOID pGetProcAddress,
LPVOID pResidentData,
DWORD nResidentDataSize);
ASM Prototype:
PostOperativePluginV2 PROTO stdcall pLoadLibrary:DWORD,\
pGetProcAddress:DWORD,\
pResidentData:DWORD,\
nResidentDataSize:DWORD
Return Value:
ERROR_SUCCESS (0) = success, continue decompression/reconstruction.
ERROR_FATAL (1) = error, this process should immediately exit.
Parameter Descriptions:
pLoadLibrary = pointer to LoadLibraryA.
pGetProcAddress = pointer to GetProcAddress.
pResidentData = pointer to the resident data storage area.
nResidentDataSize = size, in bytes, of the resident data.
Notes:
None.
Encryption Plug-in: Function: DecryptPlug-inV2
Brief: This plug-in is copied into the PECompact loader placed into the host executable. It is invoked at runtime before each data block is sent to the decompression procedure for processing.
Export Name: PostOperativePluginV2
Maximum Size: 1024 bytes
Plug-in Type: TRANSIENT
C Prototype:
DWORD DecryptPluginV2(HMODULE pLoadLibrary,
LPVOID pGetProcAddress,
LPVOID pResidentData,
DWORD nResidentDataSize,
LPVOID pSource,
DWORD nDataSize,
LPVOID pDestination);
ASM Prototype:
DecryptPluginV2 PROTO stdcall pLoadLibrary:DWORD,\
pGetProcAddress:DWORD,\
pResidentData:DWORD,\
nResidentDataSize:DWORD,\
pSource:DWORD,\
nDataSize:DWORD,\
pDestination:DWORDs
Return Value: Size of processed data or zero if error.
Parameter Descriptions:
pLoadLibrary = pointer to LoadLibraryA.
pGetProcAddress = pointer to GetProcAddress.
pResidentData = pointer to the resident data storage area.
nResidentDataSize = size, in bytes, of the resident data.
pSource = pointer to the start of the data block.
nDataSize = size of the data block pointed to be pSource.
pDestination = pointer to the destination buffer for the processed data block.
Notes:
This plug-in must undo what EncryptPlug-inV2 did to the data block at time of compression and store the result in the buffer pointed to by pDestination. To help in data alignment and to provide extra storage, each buffer is guaranteed to be of this size:
((nDataSize+15)/8)*8
This plug-in should return the new size of the data.
Encryption Plug-in: Function: EncryptPluginV2
Brief: This function is called by PECompact itself while the host executable is being compressed. It is invoked once for each data block, immediately after compression of that data block.
Export Name: EncryptPluginV2
Maximum Size: no maximum.
Plug-in Type: STATIC
C Prototype:
DWORD EncryptPluginV2(HMODULE pLoadLibrary,
LPVOID pGetProcAddress,
LPVOID pResidentData,
DWORD nResidentDataSize,
LPVOID pSource,
DWORD nDataSize,
LPVOID pDestination);
ASM Prototype:
EncryptPluginV2 PROTO stdcall pLoadLibrary:DWORD,\
pGetProcAddress:DWORD,\
pResidentData:DWORD,\
nResidentDataSize:DWORD,\
pSource:DWORD,\
nDataSize:DWORD,\
pDestination:DWORDs
Return Value: Size of processed data or zero if error.
Parameter Descriptions:
pLoadLibrary = pointer to LoadLibraryA.
pGetProcAddress = pointer to GetProcAddress.
pResidentData = pointer to the resident data storage area.
nResidentDataSize = size, in bytes, of the resident data.
pSource = pointer to the start of the data block.
nDataSize = size of the data block pointed to be pSource.
pDestination = pointer to the destination buffer for the processed data block.
Notes:
This plug-in must undo what DecryptPlug-inV2 will do to the data block and store the resulting data in the buffer pointed to by pDestination. To help in data alignment and to provide extra storage, each buffer is guaranteed to be of this size:
((nDataSize+15)/8)*8
This plug-in should return the new size of the data.
Encryption Plug-in: Function: InitEncryptionPluginV2
Brief: This function is called by PECompact itself while the host executable is being compressed. It is invoked once at the beginning of compression and before any call to EncryptPlug-inV2 is done.
Export Name: InitEncryptionPluginV2
Maximum Size: no maximum.
Plug-in Type: STATIC
C Prototype:
DWORD InitEncryptionPluginV2(HMODULE pLoadLibrary,
LPVOID pGetProcAddress,
LPVOID pResidentData,
DWORD nResidentDataSize,
HINSTANCE hInstance,
LPVOID pUserData,
DWORD nUserDataLen);
ASM Prototype:
InitEncryptionPluginV2 PROTO stdcall pLoadLibrary:DWORD,\
pGetProcAddress:DWORD,\
pResidentData:DWORD,\
nResidentDataSize:DWORD,\
hInstance:DWORD,\
pUserData:DWORD,\
nUserDataLen:DWORD
Return Value:
ERROR_SUCCESS (0) = successful termination.
ERROR_FATAL (1) = there was an error that requires the compressor to stop compression of the executable.
ERROR_NONFATAL (2) = there was an error, but compression of the executable should still continue.
Parameter Descriptions:
pLoadLibrary = pointer to LoadLibraryA.
pGetProcAddress = pointer to GetProcAddress.
pResidentData = pointer to the resident data storage area.
nResidentDataSize = size, in bytes, of the resident data.
hInstance = module handle of the parent instance.
pUserData = pointer to a block of optional text that may have been provided by the user via the command line parameter “/$UserData=”.
nUserDataLen = length of the user data.
Notes:
None.
GetProcAddressHook Plug-in
Brief: This function is called by the PECompact loader at runtime of the compressed executable. It is invoked every time the loader needs to retrieve an address of an API. This plugin is intended to facilitate API hooking.
Export Name: GetProcAddressHookPluginV2
Maximum Size: no maximum.
Plug-in Type: STATIC
C Prototype:
DWORD GetProcAddressHookPluginV2(HMODULE pLoadLibrary,
LPVOID pGetProcAddress,
LPVOID pResidentData,
DWORD nResidentDataSize,
HMODULE hModule,
LPSTR pszApiName);
ASM Prototype:
GetProcAddressHookPluginV2 PROTO stdcall pLoadLibrary:DWORD,\
pGetProcAddress:DWORD,\
pResidentData:DWORD,\
nResidentDataSize:DWORD,\
hModule:DWORD,\
pszApiName:DWORD
Return Value:
Zero if error, else address of API indicated by hModule and pszApiName.
Parameter Descriptions:
pLoadLibrary = pointer to LoadLibraryA.
pGetProcAddress = pointer to GetProcAddress.
pResidentData = pointer to the resident data storage area.
nResidentDataSize = size, in bytes, of the resident data.
hModule = module handle for the API being imported.
pszApiName = Pointer to API name *OR* ordinal number (follows same rules as
GetProcAddress).
Notes:
None.
ExtraData Plug-in
his
plug-in differs from the others, in that it is merely a text or data file
containing data that will be inserted verbatim into the compressed
portable executable. It will be inserted following the object table,
which is located immediately after the portable executable header. The
ExtraData plug-in is intended to facilitate introduction of copyright messages
into the binary, but can be used to insert any other data. It has a maximum
size of 512 bytes.
IV. Registration / Purchasing Information
For purchasing information please visit http://www.CollakeSoftware.com/Purchase.htm .